Skip to content

feat(tui): add manual compact command#716

Open
ousamabenyounes wants to merge 2 commits into
usestrix:mainfrom
ousamabenyounes:fix/issue-680
Open

feat(tui): add manual compact command#716
ousamabenyounes wants to merge 2 commits into
usestrix:mainfrom
ousamabenyounes:fix/issue-680

Conversation

@ousamabenyounes

Copy link
Copy Markdown
Contributor

Summary

Fix #680

  • Add /compact and /compress handling in the interactive TUI message path.
  • Force the SDK session compaction pipeline for the selected agent instead of forwarding the slash command as normal chat.
  • Record a system feedback message and document the interactive command.

Test verification (RED -> GREEN)

  • RED check with production files reverted:
    uv run pytest tests/test_manual_compact.py -q
    Result: 3 failed; the coordinator lacked compact_agent_session, and slash commands were not routed to compaction.

  • GREEN check with fix applied:
    uv run pytest tests/test_manual_compact.py tests/test_execution.py -q
    Result: 6 passed.

Additional checks

  • uv run ruff check strix/core/agents.py strix/interface/tui/messages.py strix/interface/tui/live_view.py tests/test_manual_compact.py
  • uv run ruff format --check strix/core/agents.py strix/interface/tui/messages.py strix/interface/tui/live_view.py tests/test_manual_compact.py
  • uv run mypy strix/core

Generated by Ora Studio
Vibe coded by ousamabenyounes

@greptile-apps

greptile-apps Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds /compact and /compress as interactive TUI commands that trigger SDK session compaction on the selected agent instead of forwarding the text as a normal chat message, and records a system feedback message in the live view on completion.

  • AgentCoordinator.compact_agent_session() is added to force the SDK compaction pipeline for a named agent, guarded by the existing _lock and gated on is_openai_responses_compaction_aware_session.
  • send_user_message_to_agent intercepts the two slash commands and dispatches compact_agent_session via run_coroutine_threadsafe, with a done callback that writes a success/failure notice back to the live view.
  • A new test file verifies both command aliases trigger compaction without forwarding a chat message to the agent.

Confidence Score: 3/5

The core compaction logic is sound, but the done-callback path writes to TuiLiveView from the event loop thread without any synchronization, which is a new concurrency pattern not present in the existing send flow.

The new _record_compaction_result callback calls live_view.record_system_message() from the event loop thread while the TUI input thread can concurrently call live_view.record_user_message() for any subsequent user input while compaction is in flight. TuiLiveView has no locks, so _next_event_id and self.events can be written by two threads simultaneously. Every prior done callback in the codebase (_log_delivery_failure) only logged — none mutated shared UI state — making this the first cross-thread live view write introduced by this PR.

strix/interface/tui/messages.py — the _record_compaction_result done callback and its thread interaction with TuiLiveView; strix/core/agents.py — the missing explicit None-session guard in compact_agent_session.

Important Files Changed

Filename Overview
strix/interface/tui/messages.py Routes /compact//compress commands to session compaction instead of normal send; the done callback mutates TuiLiveView from the event loop thread without synchronization, creating a race with TUI-thread writes for concurrent messages.
strix/core/agents.py Adds compact_agent_session which forces SDK session compaction; logic mirrors send() but lacks an explicit session is None guard, producing a misleading warning message when no session is attached.
strix/interface/tui/live_view.py Adds record_system_message method mirroring record_user_message with a different role; straightforward addition with no issues.
tests/test_manual_compact.py New test file covering the compaction flow; uses a real event loop on a background thread, correctly validates both command aliases and the no-agent-message invariant.
README.md Documents the new /compact and /compress interactive commands; accurate and concise.
Prompt To Fix All With AI
Fix the following 3 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 3
strix/interface/tui/messages.py:64-79
**Cross-thread mutation of `TuiLiveView` via done callback**

`_record_compaction_result` calls `live_view.record_system_message()` from the event loop thread (done callbacks on `concurrent.futures.Future` run on the thread that set the result, which is the event loop thread for `run_coroutine_threadsafe`). Meanwhile, callers on the TUI input thread can invoke `live_view.record_user_message()` for a subsequent message while compaction is in flight. Both paths write to `TuiLiveView.events` and increment `_next_event_id`, neither of which is protected by a lock. If a second user message arrives before the compaction coroutine finishes, these two writes race, potentially producing duplicate event IDs or a corrupted event list.

### Issue 2 of 3
strix/core/agents.py:158-181
**Misleading log when session is not yet attached**

When `compact_agent_session` is called before `attach_runtime` has set a session, `session` is `None`. The code passes `None` straight to `is_openai_responses_compaction_aware_session`, which will return `False`, causing the log to read "SDK session does not support compaction" — even though the actual problem is that no session is attached at all. The existing `send()` method handles this with an explicit `None` guard and a distinct, accurate message. Without the same guard here, a developer debugging a "compaction not working" report will look at the wrong place.

### Issue 3 of 3
strix/interface/tui/messages.py:71-79
**Exception and "not supported" both surface as "unavailable"**

When `compact_agent_session` raises (e.g., a transient network failure during `run_compaction`), `future.result()` re-raises inside `_record_compaction_result`, `compacted` is set to `False`, and the UI shows `"Context compaction is unavailable for this agent."` — the same message used when the SDK session structurally lacks compaction support. A transient error would mislead the user into thinking compaction is a permanent capability gap rather than something that might succeed on retry.

Reviews (1): Last reviewed commit: "feat(tui): add manual compact command" | Re-trigger Greptile

Comment thread strix/interface/tui/messages.py Outdated
Comment thread strix/core/agents.py Outdated
Comment thread strix/interface/tui/messages.py Outdated
@ousamabenyounes

Copy link
Copy Markdown
Contributor Author

Addressed the Greptile review feedback in d1ca17d.

Summary:

  • Routed compact feedback through the UI thread to avoid cross-thread TuiLiveView mutation.
  • Added an explicit no-session guard before compaction support checks.
  • Split compaction results into success, unavailable, and failed so transient failures do not show as unsupported.

Verified with:

  • uv run pytest tests/test_manual_compact.py tests/test_execution.py -q -> 9 passed
  • ruff check/format on touched files -> passed
  • uv run mypy strix/core strix/interface/tui/messages.py -> passed

Resolved the three outdated Greptile threads after this fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] Expose manual /compact command for long-running sessions with local LLMs

1 participant